一、高度纹理
高度纹理(高度图)是表面凹凸的实现方法之一。(适用于高精细度模型)
- 用一张纹理图像存储高度值。
- 然后在顶点着色器中采样高度值来升降顶点位置。
※高度纹理(高度图)还可以用于生成地形。
二、法线纹理
重新计算法线的方式(在什么空间计算):
在切线空间计算。(效率高但是通用性差)
在世界空间计算。(需要构建TtoW变换矩阵)(建议在顶点着色器中构建)
在视图空间计算。(需要构建TtoV变换矩阵)
补充:切线的属性:
切线方向Tangent对应纹理坐标的U。副切线Binormal对应纹理坐标的V。
补充:顶点切线计算:
已知:
- $Edge_1 = ΔU_1T + ΔV_1B$
- $Edge_2 = ΔU_2T + ΔV_2B$
=>
- $[\begin{matrix} E_{1x} & E_{1y} & E_{1z} \ E_{2x} & E_{2y} & E_{2z} \end{matrix}] = [\begin{matrix} ΔU_1 & ΔV_1 \ ΔU_2 & ΔV_2 \end{matrix}][\begin{matrix} T_x & T_y & T_z \ B_x & B_y & B_x \end{matrix}]$
=>
- $[\begin{matrix} ΔU_1 & ΔV_1 \ ΔU_2 & ΔV_2 \end{matrix}]^{-1}·[\begin{matrix} E_{1x} & E_{1y} & E_{1z} \ E_{2x} & E_{2y} & E_{2z} \end{matrix}] = [\begin{matrix} T_x & T_y & T_z \ B_x & B_y & B_x \end{matrix}]$
推导出:
- $[\begin{matrix} T_x & T_y & T_z \ B_x & B_y & B_x \end{matrix}] = {1 \over ΔU_1ΔV_2 - ΔU_2ΔV_1}[\begin{matrix} ΔV_2 & -ΔV_1 \ -ΔU_2 & ΔU_1 \end{matrix}][\begin{matrix} E_{1x} & E_{1y} & E_{1z} \ E_{2x} & E_{2y} & E_{2z} \end{matrix}]$
代码实现:
glm::vec3 GetTangent(vec3 pos1, vec3 pos2, vec3 pos3, vec2 uv1, vec2 uv2, vec2 uv3, vec3 normal)
{
glm::vec3 tangent;
vec3 edge1 = pos2 - pos1;
vec3 edge2 = pos3 - pos1;
vec2 deltaUV1 = uv2 - uv1;
vec2 deltaUV2 = uv3 - uv1;
GLfloat f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);
tangent.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);
tangent.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);
tangent.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);
tangent = normalize(tangent);
//glm::vec3 bitangent;
//bitangent.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);
//bitangent.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);
//bitangent.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);
//bitangent = normalize(bitangent);
return tangent;
}
(在Unity中直接在a2v结构体里用TANGENT语义声明即可使用。)
补充:TBN的施密特正交化:
TBN可能不正交,可以用施密特正交化:
vec3 T = normalize(vec3(model * vec4(tangent, 0.0)));
vec3 N = normalize(vec3(model * vec4(normal, 0.0)));
// re-orthogonalize T with respect to N
T = normalize(T - dot(T, N) * N);
// then retrieve perpendicular vector B with the cross product of T and N
vec3 B = cross(T, N);
mat3 TBN = mat3(T, B, N)